home *** CD-ROM | disk | FTP | other *** search
/ EuroCD 3 / EuroCD 3.iso / Programming / vbcc / machines / ppc / machine.c next >
Encoding:
C/C++ Source or Header  |  1998-06-24  |  44.3 KB  |  1,277 lines

  1. /*  Code generator for a PPC RISC cpu with 32 general purpose,  */
  2. /*  32 floating point and 8 condition code registers.           */
  3.  
  4. #include "supp.h"
  5.  
  6. static char FILE_[]=__FILE__;
  7.  
  8. /*  Public data that MUST be there.                             */
  9.  
  10. /* Name and copyright. */
  11. char cg_copyright[]="vbcc code-generator for PPC V0.2g (c) in 1997 by Volker Barthelmann";
  12.  
  13. /*  Commandline-flags the code-generator accepts                */
  14. int g_flags[MAXGF]={VALFLAG,VALFLAG,0,0,0,0,
  15.                     0,0,0,0,0};
  16. char *g_flags_name[MAXGF]={"cpu","fpu","const-in-data","sd","merge-constants","fsub-zero",
  17.                            "elf","amiga-align","no-regnames","peephole","setccs"};
  18. union ppi g_flags_val[MAXGF];
  19.  
  20. /*  Alignment-requirements for all types in bytes.              */
  21. zlong align[16];
  22.  
  23. /*  Alignment that is sufficient for every object.              */
  24. zlong maxalign;
  25.  
  26. /*  CHAR_BIT for the target machine.                            */
  27. zlong char_bit;
  28.  
  29. /*  Tabelle fuer die Groesse der einzelnen Typen                */
  30. zlong sizetab[16];
  31.  
  32. /*  Minimum and Maximum values each type can have.              */
  33. /*  Must be initialized in init_cg().                           */
  34. zlong t_min[32];
  35. zulong t_max[32];
  36.  
  37. /*  Names of all registers.                                     */
  38. char *regnames[MAXR+1]={"noreg",
  39.                         "r0","r1","r2","r10","r9","r8","r7","r6",
  40.                         "r5","r4","r3","r11","r12","r13","r14","r15",
  41.                         "r16","r17","r18","r19","r20","r21","r22","r23",
  42.                         "r24","r25","r26","r27","r28","r29","r30","r31",
  43.                         "f9","f10","f0","f11","f12","f13","f8","f7",
  44.                         "f6","f5","f4","f3","f2","f1","f14","f15",
  45.                         "f16","f17","f18","f19","f20","f21","f22","f23",
  46.                         "f24","f25","f26","f27","f28","f29","f30","f31",
  47.                         "cr0","cr1","cr2","cr3","cr4","cr5","cr6","cr7",
  48.                         "cnt"};
  49.  
  50. /*  The Size of each register in bytes.                         */
  51. zlong regsize[MAXR+1];
  52.  
  53. /*  Type which can store each register. */
  54. struct Typ *regtype[MAXR+1];
  55.  
  56. /*  regsa[reg]!=0 if a certain register is allocated and should */
  57. /*  not be used by the compiler pass.                           */
  58. int regsa[MAXR+1];
  59.  
  60. /*  Specifies which registers may be scratched by functions.    */
  61. int regscratch[MAXR+1]={0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
  62.                           0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  63.                           1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
  64.                           0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  65.                           1,1,0,0,0,1,1,1,1};
  66.  
  67. struct reg_handle empty_reg_handle={0,0};
  68.  
  69.  
  70. /****************************************/
  71. /*  Private data and functions.         */
  72. /****************************************/
  73.  
  74. static char *mregnames[MAXR+1];
  75.  
  76. static long malign[16]=  {1,1,2,4,4,4,8,1,4,1,1,1,4,1};
  77. static long msizetab[16]={1,1,2,4,4,4,8,0,4,0,0,0,4,0};
  78.  
  79. static struct Typ ltyp={LONG},ldbl={DOUBLE},lchar={CHAR};
  80.  
  81. static int r2=3;                   /*  reserved or toc                     */
  82. static int r3=11;                  /*  return value                        */
  83. static int sp=2;                   /*  Stackpointer                        */
  84. static int fp=2;                   /*  Framepointer                        */
  85. static int sd=14;                  /*  SmallDataPointer                    */
  86. static int t1=12,t2=13,t3=1;       /*  Temporaries used by code generator  */
  87. static int f1=33,f2=34,f3=35;      /*  Temporaries used by code generator  */
  88.  
  89. #define DATA 0
  90. #define BSS 1
  91. #define CODE 2
  92. #define RODATA 3
  93.  
  94. static int section=-1,newobj,crsave;
  95. static char *codename="\t.text\n",*dataname="\t.data\n",*bssname="",*rodataname="\t.section\t.rodata\n";
  96. static int is_const(struct Typ *);
  97. static char *labprefix="l",*idprefix="_";
  98. static long frameoffset,pushed,maxpushed,framesize,localoffset;
  99. static void probj2(FILE *f,struct obj *p,int t);
  100.  
  101. static struct fpconstlist {
  102.   struct fpconstlist *next;
  103.   int label,typ;
  104.   union atyps val;
  105. } *firstfpc;
  106.  
  107. static int addfpconst(struct obj *o,int t)
  108. {
  109.   struct fpconstlist *p=firstfpc;
  110.   t&=NQ;
  111.   if(g_flags[4]&USEDFLAG){
  112.     for(p=firstfpc;p;p=p->next){
  113.       if(t==p->typ){
  114.         eval_const(&p->val,t);
  115.         if(t==FLOAT&&zdeqto(vdouble,zf2zd(o->val.vfloat))) return(p->label);
  116.         if(t==DOUBLE&&zdeqto(vdouble,o->val.vdouble)) return(p->label);
  117.       }
  118.     }
  119.   }
  120.   p=mymalloc(sizeof(struct fpconstlist));
  121.   p->next=firstfpc;
  122.   p->label=++label;
  123.   p->typ=t;
  124.   p->val=o->val;
  125.   firstfpc=p;
  126.   return(p->label);
  127. }
  128.  
  129. #define REG_IND 1
  130. #define IMM_IND 2
  131.  
  132. static struct obj *cam(int flags,int base,long offset)
  133. /*  Initializes an addressing-mode structure and returns a pointer to   */
  134. /*  that object. Will not survive a second call!                        */
  135. {
  136.   static struct obj obj;
  137.   static struct AddressingMode am;
  138.   obj.am=&am;
  139.   am.flags=flags;
  140.   am.base=base;
  141.   am.offset=offset;
  142.   return(&obj);
  143. }
  144.  
  145. static char *ldt[]={"","bz","ha","wz","wz","fs","fd","","wz","","","","","","","",
  146.                     "","bz","hz","wz","wz"};
  147. static char *sdt[]={"","b","h","w","w","fs","fd","","w","","","","","","","",
  148.                     "","b","h","w","w"};
  149.  
  150. static void load_address(FILE *f,int r,struct obj *o,int typ)
  151. /*  Generates code to load the address of a variable into register r.   */
  152. {
  153.   if(!(o->flags&VAR)) ierror(0);
  154.   if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER){
  155.     if(zl2l(o->v->offset)>=0){
  156.       fprintf(f,"\taddi\t%s,%s,%ld\n",mregnames[r],mregnames[sp],(long)(zl2l(o->v->offset)+frameoffset+zl2l(o->val.vlong)));
  157.     }else{
  158.       fprintf(f,"\taddi\t%s,%s,%ld\n",mregnames[r],mregnames[sp],(long)(framesize+8-zl2l(o->v->offset)-zl2l(maxalign)+zl2l(o->val.vlong)));
  159.     }
  160.   }else{
  161.     fprintf(f,"\tlis\t%s,",mregnames[r]);
  162.     probj2(f,o,typ);fprintf(f,"@ha\n");
  163.     fprintf(f,"\taddi\t%s,%s,",mregnames[r],mregnames[r]);
  164.     probj2(f,o,typ);fprintf(f,"@l\n");
  165.   }
  166. }
  167. static void load_reg(FILE *f,int r,struct obj *o,int typ,int tmp)
  168. /*  Generates code to load a memory object into register r. tmp is a    */
  169. /*  general purpose register which may be used. tmp can be r.           */
  170. {
  171.   typ&=NU;
  172.   if(o->flags&KONST){
  173.     long l;
  174.     eval_const(&o->val,typ);
  175.     if(typ==FLOAT||typ==DOUBLE){
  176.       int lab;
  177.       if((g_flags[5]&USEDFLAG)&&zdeqto(vdouble,d2zd(0.0))){
  178.         fprintf(f,"\tfsub\t%s,%s,%s\n",mregnames[r],mregnames[r],mregnames[r]);
  179.         return;
  180.       }
  181.       lab=addfpconst(o,typ);
  182.       fprintf(f,"\tlis\t%s,%s%d@ha\n",mregnames[tmp],labprefix,lab);
  183.       fprintf(f,"\tl%s\t%s,%s%d@l(%s)\n",ldt[typ],mregnames[r],labprefix,lab,mregnames[tmp]);
  184.       return;
  185.     }
  186.     if(zlleq(vlong,l2zl(32767))&&zlleq(l2zl(-32768),vlong)){
  187.       fprintf(f,"\tli\t%s,%ld\n",mregnames[r],zl2l(vlong));
  188.     }else{
  189.       l=zl2l(zs2zl(zl2zs(zland(zlrshift(vlong,l2zl(16L)),l2zl(65535L)))));
  190.       fprintf(f,"\tlis\t%s,%ld\n",mregnames[r],l);
  191.       l=zl2l(zland(vlong,l2zl(65535L)));
  192.       fprintf(f,"\tori\t%s,%s,%ld\n",mregnames[r],mregnames[r],l);
  193.     }
  194.     return;
  195.   }
  196.   if((o->flags&VAR)&&(o->v->storage_class==EXTERN||o->v->storage_class==STATIC)){
  197.     if(o->flags&VARADR){
  198.       load_address(f,r,o,POINTER);
  199.     }else{
  200.       fprintf(f,"\tlis\t%s,",mregnames[tmp]);
  201.       probj2(f,o,typ);fprintf(f,"@ha\n");
  202.       fprintf(f,"\tl%s\t%s,",ldt[typ],mregnames[r]);
  203.       probj2(f,o,typ);fprintf(f,"@l(%s)\n",mregnames[tmp]);
  204.     }
  205.   }else{
  206.     if((o->flags&(DREFOBJ|REG))==REG){
  207.       if(r!=o->reg)
  208.         fprintf(f,"\t%smr\t%s,%s\n",r>=33?"f":"",mregnames[r],mregnames[o->reg]);
  209.     }else{
  210.       fprintf(f,"\tl%s\t%s,",ldt[typ],mregnames[r]);
  211.       probj2(f,o,typ);fprintf(f,"\n");
  212.     }
  213.   }
  214.   if(typ==CHAR) fprintf(f,"\textsb\t%s,%s\n",mregnames[r],mregnames[r]);
  215. }
  216.  
  217.  
  218. static void store_reg(FILE *f,int r,struct obj *o,int typ)
  219. /*  Generates code to store register r into memory object o.            */
  220. {
  221.   if((o->flags&VAR)&&(o->v->storage_class==EXTERN||o->v->storage_class==STATIC)){
  222.     int tmp=t1;
  223.     if(tmp==r) tmp=t2;
  224.     fprintf(f,"\tlis\t%s,",mregnames[tmp]);
  225.     probj2(f,o,typ);fprintf(f,"@ha\n");
  226.     fprintf(f,"\tst%s\t%s,",sdt[typ],mregnames[r]);
  227.     probj2(f,o,typ);fprintf(f,"@l(%s)\n",mregnames[tmp]);
  228.     return;
  229.   }
  230.   fprintf(f,"\tst%s\t%s,",sdt[typ&NU],mregnames[r]);
  231.   probj2(f,o,typ);fprintf(f,"\n");
  232. }
  233.  
  234. static long pof2(zulong x)
  235. /*  Yields log2(x)+1 oder 0. */
  236. {
  237.   zulong p;int ln=1;
  238.   p=ul2zul(1L);
  239.   while(ln<=32&&zulleq(p,x)){
  240.     if(zuleqto(x,p)) return(ln);
  241.     ln++;p=zuladd(p,p);
  242.   }
  243.   return(0);
  244. }
  245.  
  246. static char *dct[]={"","byte","uahalf","uaword","uaword","uaword","uaword"};
  247. static struct IC *do_refs(FILE *,struct IC *);
  248. static void pr(FILE *,struct IC *);
  249. static void function_top(FILE *,struct Var *,long);
  250. static void function_bottom(FILE *f,struct Var *,long);
  251.  
  252. #define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
  253.  
  254. static int q1reg,q2reg,zreg;
  255.  
  256. static char *ccs[]={"eq","ne","lt","ge","le","gt",""};
  257. static char *logicals[]={"or","xor","and"};
  258. static char *arithmetics[]={"slw","srw","add","sub","mullw","divw","mod"};
  259. static char *isimm[]={"","i"};
  260.  
  261. static struct IC *do_refs(FILE *f,struct IC *p)
  262. /*  Does some pre-processing like fetching operands from memory to      */
  263. /*  registers etc.                                                      */
  264. {
  265.   int typ=p->typf,typ1,reg,c=p->code;
  266.  
  267.   if(c==CONVCHAR) typ=CHAR;
  268.   if(c==CONVUCHAR) typ=UNSIGNED|CHAR;
  269.   if(c==CONVSHORT) typ=SHORT;
  270.   if(c==CONVUSHORT) typ=UNSIGNED|SHORT;
  271.   if(c==CONVINT) typ=LONG;
  272.   if(c==CONVUINT) typ=UNSIGNED|LONG;
  273.   if(c==CONVLONG) typ=LONG;
  274.   if(c==CONVULONG) typ=UNSIGNED|LONG;
  275.   if(c==CONVFLOAT) typ=FLOAT;
  276.   if(c==CONVDOUBLE) typ=DOUBLE;
  277.   if(c==CONVPOINTER) typ=UNSIGNED|LONG;
  278.  
  279.   if(c==SUB&&(p->q2.flags&KONST)&&(typ&NQ)<=LONG){
  280.     eval_const(&p->q2.val,typ);
  281.     if(zlleq(vlong,l2zl(32768L))&&zlleq(l2zl(-32767L),vlong)){
  282.       union atyps val;
  283.       p->code=c=ADD;
  284.       val.vlong=zlsub(l2zl(0L),vlong);
  285.       eval_const(&val,LONG);
  286.       insert_const2(&p->q2.val,typ);
  287.     }
  288.   }
  289.  
  290.   q1reg=q2reg=zreg=0;
  291.   if(p->q1.flags®) q1reg=p->q1.reg;
  292.   if(p->q2.flags®) q2reg=p->q2.reg;
  293.   if((p->z.flags&(REG|DREFOBJ))==REG) zreg=p->z.reg;
  294.  
  295.   if((p->q1.flags&(KONST|DREFOBJ))==KONST){
  296.     eval_const(&p->q1.val,typ);
  297.     if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) reg=f1; else reg=t1;
  298.     if(c==ASSIGN&&zreg) reg=zreg;
  299.     if(c==SETRETURN&&p->z.reg) reg=p->z.reg;
  300.     if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE||c==DIV||c==ASSIGN||c==PUSH||c==SETRETURN||c==LSHIFT||c==RSHIFT||c==COMPARE){
  301.       load_reg(f,reg,&p->q1,typ,t1);
  302.       q1reg=reg;
  303.     }else{
  304.       if((typ&NQ)<=LONG){
  305.         if((c>=OR&&c<=AND)||(c==COMPARE&&(typ&UNSIGNED))){
  306.           if(!zulleq(vulong,ul2zul(65535UL))){
  307.             load_reg(f,reg,&p->q1,typ,t1);
  308.             q1reg=reg;
  309.           }
  310.         }else{
  311.           if(!zlleq(vlong,l2zl(32767L))||!zlleq(l2zl(-32768L),vlong)){
  312.             load_reg(f,reg,&p->q2,typ,t1);
  313.             q1reg=reg;
  314.           }
  315.         }
  316.       }
  317.     }
  318.   }else if(c!=ADDRESS){
  319.     if(p->q1.flags&&!q1reg){
  320.       if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) reg=f1; else reg=t1;
  321.       if((c==ASSIGN||(c>=CONVCHAR&&c<=CONVULONG&&c!=CONVFLOAT&&c!=CONVDOUBLE))&&zreg>=1&&zreg<=32) reg=zreg;
  322.       if(c==SETRETURN&&p->z.reg) reg=p->z.reg;
  323.       if(p->q1.flags&DREFOBJ) {typ1=POINTER;reg=t1;} else typ1=typ;
  324.       if((typ1&NQ)<=POINTER){
  325.         int m=p->q1.flags;
  326.         p->q1.flags&=~DREFOBJ;
  327.         load_reg(f,reg,&p->q1,typ1,t1);
  328.         p->q1.flags=m;
  329.         q1reg=reg;
  330.       }
  331.     }
  332.     if((p->q1.flags&DREFOBJ)&&(typ&NQ)<=POINTER){
  333.       if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) reg=f1; else reg=t1;
  334.       if((c==ASSIGN||(c>=CONVCHAR&&c<=CONVULONG&&c!=CONVFLOAT&&c!=CONVDOUBLE))&&zreg>=1&&zreg<=32) reg=zreg;
  335.       if(c==SETRETURN&&p->z.reg) reg=p->z.reg;
  336.       if(p->q1.am)
  337.         load_reg(f,reg,&p->q1,typ,t1);
  338.       else
  339.         load_reg(f,reg,cam(IMM_IND,q1reg,0),typ,t1);
  340.       q1reg=reg;
  341.     }
  342.   }
  343.   typ=p->typf;
  344.   if((p->q2.flags&(KONST|DREFOBJ))==KONST){
  345.     eval_const(&p->q2.val,typ);
  346.     if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) reg=f2; else reg=t2;
  347.     if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE||c==DIV||c==SUB||c==MOD){
  348.       load_reg(f,reg,&p->q2,typ,t2);
  349.       q2reg=reg;
  350.     }else{
  351.       if((typ&NQ)<=LONG){
  352.         if((c>=OR&&c<=AND)||(c==COMPARE&&(typ&UNSIGNED))){
  353.           if(!zulleq(vulong,ul2zul(65535UL))){
  354.             load_reg(f,reg,&p->q2,typ,t2);
  355.             q2reg=reg;
  356.           }
  357.         }else{
  358.           if(!zlleq(vlong,l2zl(32767L))||!zlleq(l2zl(-32768L),vlong)){
  359.             load_reg(f,reg,&p->q2,typ,t2);
  360.             q2reg=reg;
  361.           }
  362.         }
  363.       }
  364.     }
  365.   }else{
  366.     if(p->q2.flags&&!q2reg){
  367.       if(p->q2.flags&DREFOBJ) typ1=POINTER; else typ1=typ;
  368.       if((typ1&NQ)==FLOAT||(typ1&NQ)==DOUBLE) reg=f2; else reg=t2;
  369.       if((typ1&NQ)<=POINTER){
  370.         int m=p->q2.flags;
  371.         p->q2.flags&=~DREFOBJ;
  372.         load_reg(f,reg,&p->q2,typ1,t2);
  373.         p->q2.flags=m;
  374.         q2reg=reg;
  375.       }
  376.     }
  377.     if((p->q2.flags&DREFOBJ)&&(typ&NQ)<=POINTER){
  378.       if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) reg=f2; else reg=t2;
  379.       if(p->q2.am)
  380.         load_reg(f,reg,&p->q2,typ,t2);
  381.       else
  382.         load_reg(f,reg,cam(IMM_IND,q2reg,0),typ,t2);
  383.       q2reg=reg;
  384.     }
  385.   }
  386.   if(p->z.flags&&!isreg(z)){
  387.     typ=p->typf;
  388.     if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) zreg=f3; else zreg=t3;
  389.   }
  390.   if(q1reg){ p->q1.flags=REG; p->q1.reg=q1reg;}
  391.   if(q2reg){ p->q2.flags=REG; p->q2.reg=q2reg;}
  392.   return(p);
  393. }
  394. static void pr(FILE *f,struct IC *p)
  395.      /*  Writes the destination register to the real destination if necessary.   */
  396. {
  397.   int typ=p->typf;
  398.   if(p->code==ADDRESS) typ=POINTER;
  399.   if(p->z.flags){
  400.     if(!isreg(z)){
  401.       if(p->z.flags&DREFOBJ){
  402.         if(p->z.flags®){
  403.           if(p->z.am)
  404.             store_reg(f,zreg,&p->z,typ);
  405.           else
  406.             store_reg(f,zreg,cam(IMM_IND,p->z.reg,0),typ);
  407.         }else{
  408.           int r;
  409.           if(t1==zreg) r=t2; else r=t1;
  410.           load_reg(f,r,&p->z,POINTER,r);
  411.           store_reg(f,zreg,cam(IMM_IND,r,0),typ);
  412.         }
  413.       }else{
  414.         store_reg(f,zreg,&p->z,typ);
  415.       }
  416.     }else{
  417.       if(p->z.reg!=zreg)
  418.         fprintf(f,"\t%smr\t%s,%s\n",zreg>=33?"f":"",mregnames[p->z.reg],mregnames[zreg]);
  419.     }
  420.   }
  421. }
  422.  
  423. static void probj2(FILE *f,struct obj *p,int t)
  424. /*  Prints an object.                               */
  425. {
  426.   if(p->am){
  427.     if(p->am->flags==REG_IND) fprintf(f,"%s(%s)",mregnames[p->am->offset],mregnames[p->am->base]);
  428.     if(p->am->flags==IMM_IND) fprintf(f,"%ld(%s)",p->am->offset,mregnames[p->am->base]);
  429.     return;
  430.   }
  431.   /*  if(p->flags&DREFOBJ) fprintf(f,"(");*/
  432.   if(p->flags&VAR) {
  433.     if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER){
  434.       if(p->flags®){
  435.         fprintf(f,"%s",mregnames[p->reg]);
  436.       }else{
  437.         if(zl2l(p->v->offset)>=0){
  438.           fprintf(f,"%ld(%s)",(long)(zl2l(p->v->offset)+zl2l(p->val.vlong)+frameoffset),mregnames[sp]);
  439.         }else{
  440.           fprintf(f,"%ld(%s)",(long)(framesize+8-zl2l(p->v->offset)-zl2l(maxalign)+zl2l(p->val.vlong)),mregnames[sp]);
  441.         }
  442.       }
  443.     }else{
  444.       if(!zleqto(l2zl(0L),p->val.vlong)){printval(f,&p->val,LONG,0);fprintf(f,"+");}
  445.       if(p->v->storage_class==STATIC&&(p->v->vtyp->flags&NQ)!=FUNKT){
  446.         fprintf(f,"%s%ld",labprefix,zl2l(p->v->offset));
  447.       }else{
  448.         fprintf(f,"%s%s",idprefix,p->v->identifier);
  449.       }
  450.     }
  451.   }
  452.   if((p->flags®)&&!(p->flags&VAR)) fprintf(f,"%s",mregnames[p->reg]);
  453.   if(p->flags&KONST){
  454.     printval(f,&p->val,t&NU,0);
  455.   }
  456.   /*  if(p->flags&DREFOBJ) fprintf(f,")");*/
  457. }
  458. static void peephole(struct IC *p)
  459. /* Try to use addressing modes */
  460. {
  461.   int c,r;long of;
  462.   for(;p;p=p->next){
  463.     c=p->code;
  464.     if((c==ADDI2P||c==SUBIFP)&&(p->q2.flags&KONST)&&isreg(q1)&&isreg(z)&&p->next){
  465.       struct IC *p2=p->next;int c2=p2->code;
  466.       eval_const(&p->q2.val,p->typf);
  467.       of=zl2l(vlong);
  468.       r=p->z.reg;
  469.       if(of>=-32768&&of<=32767&&c2!=CALL&&(c2<LABEL||c2>BRA)&&p2->next&&p2->next->code==FREEREG&&p2->next->q1.reg==r){
  470.         if(((p2->q1.flags&(REG|DREFOBJ))!=REG||p2->q1.reg!=r)&&
  471.            ((p2->q2.flags&(REG|DREFOBJ))!=REG||p2->q2.reg!=r)&&
  472.            ((p2->z.flags&(REG|DREFOBJ))!=REG||p2->z.reg!=r)){
  473.           if((p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r){
  474.             p2->q1.am=mymalloc(sizeof(struct AddressingMode));
  475.             p2->q1.am->flags=IMM_IND;
  476.             p2->q1.am->base=p->q1.reg;
  477.             p2->q1.am->offset=of;
  478.           }
  479.           if((p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
  480.             p2->q2.am=mymalloc(sizeof(struct AddressingMode));
  481.             p2->q2.am->flags=IMM_IND;
  482.             p2->q2.am->base=p->q1.reg;
  483.             p2->q2.am->offset=of;
  484.           }
  485.           if((p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
  486.             p2->z.am=mymalloc(sizeof(struct AddressingMode));
  487.             p2->z.am->flags=IMM_IND;
  488.             p2->z.am->base=p->q1.reg;
  489.             p2->z.am->offset=of;
  490.           }
  491.           p->code=NOP;p->q1.flags=p->q2.flags=p->z.flags=0;
  492.         }
  493.       }
  494.     }
  495.   }
  496. }
  497. static void function_top(FILE *f,struct Var *v,long offset)
  498. /*  Generates function top.                             */
  499. {
  500.   int i;long of;
  501.   if(section!=CODE){fprintf(f,codename);section=CODE;}
  502.   if(v->storage_class==EXTERN) fprintf(f,"\t.global\t%s%s\n",idprefix,v->identifier);
  503.   fprintf(f,"\t.align\t4\n%s%s:\n",idprefix,v->identifier);
  504.   frameoffset=8+maxpushed;
  505.   framesize=frameoffset+offset;
  506.   for(i=1;i<=64;i++){
  507.     if(regused[i]&&!regscratch[i]&&!regsa[i]){
  508.       if(i<=32) framesize+=4; else framesize+=8;
  509.     }
  510.   }
  511.   for(crsave=0,i=65;i<=72;i++)
  512.     if(regused[i]&&!regscratch[i]&&!regsa[i]) crsave=1;
  513.   if(crsave) framesize+=4;
  514.   if(framesize==8&&function_calls==0) framesize=frameoffset=0;
  515.   framesize=(framesize+15)/16*16;
  516.   if(framesize>32767) ierror(0);
  517.   if(framesize!=0)
  518.     fprintf(f,"\tstwu\t%s,-%ld(%s)\n",mregnames[sp],framesize,mregnames[sp]);
  519.   if(function_calls)
  520.     fprintf(f,"\tmflr\t%s\n\tst%s\t%s,%ld(%s)\n",mregnames[t1],sdt[LONG],mregnames[t1],framesize+4,mregnames[sp]);
  521.   of=8+maxpushed+offset;
  522.   if(crsave){
  523.     fprintf(f,"\tmfcr\t%s\n\tst%s\t%s,%ld(%s)\n",mregnames[t1],sdt[LONG],mregnames[t1],of,mregnames[sp]);
  524.     of+=4;
  525.   }
  526.   for(i=1;i<=64;i++){
  527.     if(regused[i]&&!regscratch[i]&&!regsa[i]){
  528.       if(i<=32){
  529.         fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[LONG],mregnames[i],of,mregnames[sp]);
  530.         of+=4;
  531.       }else{
  532.         fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[DOUBLE],mregnames[i],of,mregnames[sp]);
  533.         of+=8;
  534.       }
  535.     }
  536.   }
  537. }
  538. static void function_bottom(FILE *f,struct Var *v,long offset)
  539. /*  Generates function bottom.                          */
  540. {
  541.   int i;long of;
  542.   of=8+maxpushed+offset;
  543.   if(crsave){
  544.     fprintf(f,"\tl%s\t%s,%ld(%s)\n\tmtcr\t%s\n",ldt[LONG],mregnames[t1],of,mregnames[sp],mregnames[t1]);
  545.     of+=4;
  546.   }
  547.   for(i=1;i<=64;i++){
  548.     if(regused[i]&&!regscratch[i]&&!regsa[i]){
  549.       if(i<=32){
  550.         fprintf(f,"\tl%s\t%s,%ld(%s)\n",ldt[LONG],mregnames[i],of,mregnames[sp]);
  551.         of+=4;
  552.       }else{
  553.         fprintf(f,"\tl%s\t%s,%ld(%s)\n",ldt[DOUBLE],mregnames[i],of,mregnames[sp]);
  554.         of+=8;
  555.       }
  556.     }
  557.   }
  558.   if(function_calls)
  559.     fprintf(f,"\tl%s\t%s,%ld(%s)\n\tmtlr\t%s\n",ldt[LONG],mregnames[t1],framesize+4,mregnames[sp],mregnames[t1]);
  560.   if(framesize) fprintf(f,"\taddi\t%s,%s,%ld\n",mregnames[sp],mregnames[sp],framesize);
  561.   fprintf(f,"\tblr\n");
  562.   fprintf(f,"\t.type\t%s%s,@function\n",idprefix,v->identifier);
  563.   fprintf(f,"\t.size\t%s%s,$-%s%s\n",idprefix,v->identifier,idprefix,v->identifier);
  564. }
  565. static int is_const(struct Typ *t)
  566. /*  Tests if a type can be placed in the code-section.  */
  567. {
  568.     if(!(t->flags&(CONST|STRINGCONST))){
  569.         do{
  570.             if(t->flags&(CONST|STRINGCONST)) return(1);
  571.             if((t->flags&NQ)!=ARRAY) return(0);
  572.             t=t->next;
  573.         }while(1);
  574.     }else return(1);
  575. }
  576. static int balign(struct obj *o)
  577. /*  Liefert die unteren 2 Bits des Objekts. -1 wenn unklar. */
  578. {
  579.   int sc;
  580.   if(o->flags&DREFOBJ) return -1;
  581.   if(o->am) ierror(0);
  582.   if(!(o->flags&VAR)) ierror(0);
  583.   sc=o->v->storage_class;
  584.   if(sc==EXTERN||sc==STATIC){
  585.     /* Alle statischen Daten werden vom cg auf 32bit alignt. */
  586.     return zl2l(zland(o->val.vlong,l2zl(3L)));
  587.   }
  588.   if(sc==AUTO||sc==REGISTER){
  589.     zlong of=o->v->offset;
  590.     if(!zlleq(l2zl(0L),of))
  591.       of=zlsub(l2zl(0L),zladd(of,maxalign));
  592.     return zl2l(zland(zladd(of,o->val.vlong),l2zl(3L)));
  593.   }
  594.   ierror(0);
  595. }
  596.  
  597. /****************************************/
  598. /*  End of private data and functions.  */
  599. /****************************************/
  600.  
  601.  
  602. int init_cg(void)
  603. /*  Does necessary initializations for the code-generator. Gets called  */
  604. /*  once at the beginning and should return 0 in case of problems.      */
  605. {
  606.   int i;
  607.   /*  Initialize some values which cannot be statically initialized   */
  608.   /*  because they are stored in the target's arithmetic.             */
  609.   maxalign=l2zl(4L);
  610.   char_bit=l2zl(8L);
  611.   if(g_flags[7]&USEDFLAG){
  612.     malign[INT]=malign[LONG]=malign[POINTER]=malign[FLOAT]=malign[DOUBLE]=2;
  613.   }
  614.   for(i=0;i<16;i++){
  615.     sizetab[i]=l2zl(msizetab[i]);
  616.     align[i]=l2zl(malign[i]);
  617.   }
  618.   for(i=0;i<=MAXR;i++) mregnames[i]=regnames[i];
  619.   for(i= 1;i<=32;i++){
  620.     regsize[i]=l2zl(4L);
  621.     regtype[i]=<yp;
  622.     if(g_flags[8]&USEDFLAG) mregnames[i]++;
  623.   }
  624.   for(i=33;i<=64;i++){
  625.     regsize[i]=l2zl(8L);
  626.     regtype[i]=&ldbl;
  627.     if(g_flags[8]&USEDFLAG) mregnames[i]++;
  628.   }
  629.   for(i=65;i<=72;i++){
  630.     regsize[i]=l2zl(1L);
  631.     regtype[i]=&lchar;
  632.     if(g_flags[8]&USEDFLAG) mregnames[i]+=2;
  633.   }
  634.  
  635.   /*  Use multiple ccs.   */
  636.   multiple_ccs=1;
  637.  
  638.   /*  Initialize the min/max-settings. Note that the types of the     */
  639.   /*  host system may be different from the target system and you may */
  640.   /*  only use the smallest maximum values ANSI guarantees if you     */
  641.   /*  want to be portable.                                            */
  642.   /*  That's the reason for the subtraction in t_min[INT]. Long could */
  643.   /*  be unable to represent -2147483648 on the host system.          */
  644.   t_min[UNSIGNED|CHAR]=t_min[UNSIGNED|SHORT]=t_min[UNSIGNED|INT]=t_min[UNSIGNED|LONG]=l2zl(0L);
  645.   t_min[CHAR]=l2zl(-128L);
  646.   t_min[SHORT]=l2zl(-32768L);
  647.   t_min[INT]=zlsub(l2zl(-2147483647L),l2zl(1L));
  648.   t_min[LONG]=t_min[INT];
  649.   t_max[CHAR]=ul2zul(127UL);
  650.   t_max[SHORT]=ul2zul(32767UL);
  651.   t_max[INT]=ul2zul(2147483647UL);
  652.   t_max[LONG]=t_max[INT];
  653.   t_max[UNSIGNED|CHAR]=ul2zul(255UL);
  654.   t_max[UNSIGNED|SHORT]=ul2zul(65535UL);
  655.   t_max[UNSIGNED|INT]=ul2zul(4294967295UL);
  656.   t_max[UNSIGNED|LONG]=t_max[UNSIGNED|INT];
  657.   /*  Reserve a few registers for use by the code-generator.      */
  658.   /*  This is not optimal but simple.                             */
  659.   regsa[t1]=regsa[t2]=regsa[t3]=1;
  660.   regsa[f1]=regsa[f2]=regsa[f3]=1;
  661.   regsa[sp]=regsa[fp]=regsa[sd]=regsa[r2]=1;
  662.   regscratch[t1]=regscratch[t2]=regscratch[t3]=0;
  663.   regscratch[f1]=regscratch[f2]=regscratch[f3]=0;
  664.   regscratch[sp]=regscratch[fp]=regscratch[sd]=regscratch[r2]=0;
  665.  
  666.   if(g_flags[6]&USEDFLAG) {labprefix=".l";idprefix="";}
  667.  
  668.   return(1);
  669. }
  670.  
  671. int freturn(struct Typ *t)
  672. /*  Returns the register in which variables of type t are returned. */
  673. /*  If the value cannot be returned in a register returns 0.        */
  674. /*  A pointer MUST be returned in a register. The code-generator    */
  675. /*  has to simulate a pseudo register if necessary.                 */
  676. {
  677.     if((t->flags&NQ)==FLOAT||(t->flags&NQ)==DOUBLE) return(46);
  678.     if((t->flags&NQ)==STRUCT||(t->flags&NQ)==UNION) return(0);
  679.     if(zlleq(szof(t),l2zl(4L))) return(11); else return(0);
  680. }
  681.  
  682. int regok(int r,int t,int mode)
  683. /*  Returns 0 if register r cannot store variables of   */
  684. /*  type t. If t==POINTER and mode!=0 then it returns   */
  685. /*  non-zero only if the register can store a pointer   */
  686. /*  and dereference a pointer to mode.                  */
  687. {
  688.     if(r==0) return(0);
  689.     t&=NQ;
  690.     if(t==0){
  691.         if(r>=65&&r<=72) return(1); else return(0);
  692.     }
  693.     if((t==FLOAT||t==DOUBLE)&&r>=33&&r<=64) return(1);
  694.     if(t==POINTER&&r>=1&&r<=32) return(1);
  695.     if(t>=CHAR&&t<=LONG&&r>=1&&r<=32) return(1);
  696.     return(0);
  697. }
  698.  
  699. int dangerous_IC(struct IC *p)
  700. /*  Returns zero if the IC p can be safely executed     */
  701. /*  without danger of exceptions or similar things.     */
  702. /*  vbcc may generate code in which non-dangerous ICs   */
  703. /*  are sometimes executed although control-flow may    */
  704. /*  never reach them (mainly when moving computations   */
  705. /*  out of loops).                                      */
  706. /*  Typical ICs that generate exceptions on some        */
  707. /*  machines are:                                       */
  708. /*      - accesses via pointers                         */
  709. /*      - division/modulo                               */
  710. /*      - overflow on signed integer/floats             */
  711. {
  712.     int c=p->code;
  713.     if((p->q1.flags&DREFOBJ)||(p->q2.flags&DREFOBJ)||(p->z.flags&DREFOBJ))
  714.         return(0);
  715.     if((c==DIV||c==MOD)&&!(p->q2.flags&KONST))
  716.         return(1);
  717.     return(0);
  718. }
  719.  
  720. int must_convert(np p,int t)
  721. /*  Returns zero if code for converting np to type t    */
  722. /*  can be omitted.                                     */
  723. /*  On the PowerPC cpu pointers and 32bit               */
  724. /*  integers have the same representation and can use   */
  725. /*  the same registers.                                 */
  726. {
  727.     int o=p->ntyp->flags,op=o&NQ,tp=t&NQ;
  728.     if(zleqto(sizetab[tp],sizetab[op])&&op!=FLOAT&&tp!=FLOAT) return(0);
  729.  
  730.     return(1);
  731. }
  732.  
  733. void gen_ds(FILE *f,zlong size,struct Typ *t)
  734. /*  This function has to create <size> bytes of storage */
  735. /*  initialized with zero.                              */
  736. {
  737.     if(newobj) fprintf(f,"%ld\n",zl2l(size));
  738.         else   fprintf(f,"\t.space\t%ld\n",zl2l(size));
  739.     newobj=0;
  740. }
  741.  
  742. void gen_align(FILE *f,zlong align)
  743. /*  This function has to make sure the next data is     */
  744. /*  aligned to multiples of <align> bytes.              */
  745. {
  746.     fprintf(f,"\t.align\t2\n");
  747. }
  748.  
  749. void gen_var_head(FILE *f,struct Var *v)
  750. /*  This function has to create the head of a variable  */
  751. /*  definition, i.e. the label and information for      */
  752. /*  linkage etc.                                        */
  753. {
  754.     int constflag;
  755.     if(v->clist) constflag=is_const(v->vtyp);
  756.     if(v->storage_class==STATIC){
  757.         if((v->vtyp->flags&NQ)==FUNKT) return;
  758.         if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&§ion!=DATA){fprintf(f,dataname);section=DATA;}
  759.         if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&§ion!=RODATA){fprintf(f,rodataname);section=RODATA;}
  760.         if(!v->clist&§ion!=BSS){fprintf(f,bssname);section=BSS;}
  761.         fprintf(f,"\t.type\t%s%ld,@object\n",labprefix,zl2l(v->offset));
  762.         fprintf(f,"\t.size\t%s%ld,%ld\n",labprefix,zl2l(v->offset),zl2l(szof(v->vtyp)));
  763.         if(section!=BSS) fprintf(f,"%s%ld:\n",labprefix,zl2l(v->offset));
  764.             else fprintf(f,"\t.lcomm\t%s%ld,",labprefix,zl2l(v->offset));
  765.         newobj=1;
  766.     }
  767.     if(v->storage_class==EXTERN){
  768.         fprintf(f,"\t.global\t%s%s\n",idprefix,v->identifier);
  769.         if(v->flags&(DEFINED|TENTATIVE)){
  770.             if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&§ion!=DATA){fprintf(f,dataname);section=DATA;}
  771.             if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&§ion!=RODATA){fprintf(f,rodataname);section=RODATA;}
  772.             if(!v->clist&§ion!=BSS){fprintf(f,bssname);section=BSS;}
  773.             fprintf(f,"\t.type\t%s%s,@object\n",idprefix,v->identifier);
  774.             fprintf(f,"\t.size\t%s%s,%ld\n",idprefix,v->identifier,zl2l(szof(v->vtyp)));
  775.             if(section!=BSS) fprintf(f,"%s%s:\n",idprefix,v->identifier);
  776.                 else fprintf(f,"\t.comm\t%s%s,",idprefix,v->identifier);
  777.             newobj=1;
  778.         }
  779.     }
  780. }
  781.  
  782. void gen_dc(FILE *f,int t,struct const_list *p)
  783. /*  This function has to create static storage          */
  784. /*  initialized with const-list p.                      */
  785. {
  786.     if((t&NQ)==POINTER) t=UNSIGNED|LONG;
  787.     fprintf(f,"\t.%s\t",dct[t&NQ]);
  788.     if(!p->tree){
  789.         if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
  790.         /*  auch wieder nicht sehr schoen und IEEE noetig   */
  791.             unsigned char *ip;
  792.             ip=(unsigned char *)&p->val.vdouble;
  793.             fprintf(f,"0x%02x%02x%02x%02x",ip[0],ip[1],ip[2],ip[3]);
  794.             if((t&NQ)==DOUBLE){
  795.                 fprintf(f,",0x%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]);
  796.             }
  797.         }else{
  798.             printval(f,&p->val,t&NU,0);
  799.         }
  800.     }else{
  801.         probj2(f,&p->tree->o,t&NU);
  802.     }
  803.     fprintf(f,"\n");newobj=0;
  804. }
  805.  
  806.  
  807. /*  The main code-generation routine.                   */
  808. /*  f is the stream the code should be written to.      */
  809. /*  p is a pointer to a doubly linked list of ICs       */
  810. /*  containing the function body to generate code for.  */
  811. /*  v is a pointer to the function.                     */
  812. /*  offset is the size of the stackframe the function   */
  813. /*  needs for local variables.                          */
  814.  
  815. void gen_code(FILE *f,struct IC *p,struct Var *v,zlong offset)
  816. /*  The main code-generation.                                           */
  817. {
  818.   int c,t,i,addbuf,varargs=0,fixedgpr,fixedfpr;
  819.   char *fpp;struct IC *m;
  820.   long of=(zl2l(offset)+3)/4*4,regbase,tmpoff;
  821.   if(DEBUG&1) printf("gen_code()\n");
  822.   for(c=1;c<=MAXR;c++) regs[c]=regsa[c];
  823.   maxpushed=0;addbuf=0;
  824.   for(m=p;m;m=m->next){
  825.     c=m->code;t=m->typf&NU;
  826.     if(c==ALLOCREG) {regs[m->q1.reg]=1;continue;}
  827.     if(c==FREEREG) {regs[m->q1.reg]=0;continue;}
  828.     if(c==COMPARE&&(m->q2.flags&KONST)){
  829.       eval_const(&m->q2.val,t);
  830.       if(zleqto(vlong,l2zl(0L))&&zdeqto(vdouble,d2zd(0.0))){
  831.         m->q2.flags=0;m->code=c=TEST;
  832.       }
  833.     }
  834.     if((t&NQ)<=LONG&&(m->q2.flags&KONST)&&(t&NQ)<=LONG&&(c==MULT||c==DIV||(c==MOD&&(t&UNSIGNED)))){
  835.       eval_const(&m->q2.val,t);
  836.       i=pof2(vlong);
  837.       if(i){
  838.         if(c==MOD){
  839.           vlong=zlsub(vlong,l2zl(1L));
  840.           m->code=AND;
  841.         }else{
  842.           vlong=l2zl(i-1);
  843.           if(c==DIV) m->code=RSHIFT; else m->code=LSHIFT;
  844.         }
  845.         c=m->code;
  846.         if((t&NU)==CHAR) m->q2.val.vchar=zl2zc(vlong);
  847.         if((t&NU)==SHORT) m->q2.val.vshort=zl2zs(vlong);
  848.         if((t&NU)==INT) m->q2.val.vint=zl2zi(vlong);
  849.         if((t&NU)==LONG) m->q2.val.vlong=vlong;
  850.         vulong=zl2zul(vlong);
  851.         if((t&NU)==(UNSIGNED|CHAR)) m->q2.val.vuchar=zul2zuc(vulong);
  852.         if((t&NU)==(UNSIGNED|SHORT)) m->q2.val.vushort=zul2zus(vulong);
  853.         if((t&NU)==(UNSIGNED|INT))  m->q2.val.vuint=zul2zui(vulong);
  854.         if((t&NU)==(UNSIGNED|LONG)) m->q2.val.vulong=vulong;
  855.       }
  856.     }
  857.     if((c==CONVFLOAT||c==CONVDOUBLE)&&t!=FLOAT&&t!=DOUBLE&&addbuf<8) addbuf=8;
  858.     if((t==FLOAT||t==DOUBLE)&&c>=CONVCHAR&&c<=CONVULONG&&addbuf<8) addbuf=8;
  859.     if(c==CALL&&maxpushed<zl2l(m->q2.val.vlong)) maxpushed=zl2l(m->q2.val.vlong);
  860.     if(c==CALL&&(m->q1.flags&VAR)&&!strcmp(m->q1.v->identifier,"__va_start")) varargs=1;
  861.   }
  862.   if(g_flags[9]&USEDFLAG) peephole(p);
  863.   if(varargs){
  864.     fixedgpr=fixedfpr=0;
  865.     for(i=0;i<v->vtyp->exact->count;i++){
  866.       c=(*v->vtyp->exact->sl)[i].styp->flags&NQ;
  867.       if(c==POINTER||c<=LONG) fixedgpr++;
  868.       if(c==FLOAT||c==DOUBLE) fixedfpr++;
  869.     }
  870.     regbase=of; /* merken */
  871.     addbuf+=96;
  872.   }
  873.   of+=addbuf;tmpoff=8+maxpushed+of;
  874.   function_top(f,v,of);
  875.   if(varargs){
  876.     regbase=frameoffset+regbase;
  877.     fpp="";
  878.     if(!(g_flags[8]&USEDFLAG)) fpp="r";
  879.     for(i=fixedgpr;i<8;i++)
  880.       fprintf(f,"\tstw\t%s%d,%ld(%s)\n",fpp,i+3,regbase+i*4,mregnames[sp]);
  881.     if(!(g_flags[8]&USEDFLAG)) fpp="f";
  882.     for(i=fixedfpr;i<8;i++)
  883.       fprintf(f,"\tstfd\t%s%d,%ld(%s)\n",fpp,i+1,regbase+32+i*8,mregnames[sp]);
  884.   }
  885.   pushed=0;
  886.   for(;p;pr(f,p),p=p->next){
  887.     c=p->code;t=p->typf;
  888.     if(c==NOP) continue;
  889.     if(c==ALLOCREG) {regs[p->q1.reg]=1;continue;}
  890.     if(c==FREEREG) {regs[p->q1.reg]=0;continue;}
  891.     if(c==LABEL) {fprintf(f,"%s%d:\n",labprefix,t);continue;}
  892.     if(c==BRA) {fprintf(f,"\tb\t%s%d\n",labprefix,t);continue;}
  893.     if(c>=BEQ&&c<BRA){
  894.       if(!(p->q1.flags®)) p->q1.reg=65;
  895.       fprintf(f,"\tb%s\t%s,%s%d\n",ccs[c-BEQ],mregnames[p->q1.reg],labprefix,t);
  896.       continue;
  897.     }
  898.     if(c==MOVETOREG){
  899.       if(p->z.reg<=32){
  900.         load_reg(f,p->z.reg,&p->q1,INT,0);
  901.       }else{
  902.         if(p->z.reg>64) ierror(0);
  903.         load_reg(f,p->z.reg,&p->q1,DOUBLE,0);
  904.       }
  905.       p->z.flags=0;
  906.       continue;
  907.     }
  908.     if(c==MOVEFROMREG){
  909.       if(p->q1.reg<=32){
  910.         store_reg(f,p->q1.reg,&p->z,INT);
  911.       }else{
  912.         if(p->q1.reg>64) ierror(0);
  913.         store_reg(f,p->q1.reg,&p->z,DOUBLE);
  914.       }
  915.       p->z.flags=0;
  916.       continue;
  917.     }
  918.     if((c==ASSIGN||c==PUSH)&&((t&NQ)>POINTER||((t&NQ)==CHAR&&zl2l(p->q2.val.vlong)!=1))){
  919.       unsigned long size,l;
  920.       int a1,a2,b;char *ld,*st;
  921.       size=zl2l(p->q2.val.vlong);
  922.       a1=balign(&p->q1);
  923.       if(c==ASSIGN) a2=balign(&p->z); else a2=0;
  924.       b=1;ld=ldt[CHAR];st=sdt[CHAR];
  925.       if(a1>=0&&a2>=0){
  926.         if(a1==0&&a2==0){
  927.           b=4;ld=ldt[INT];st=sdt[INT];
  928.         }else if((a1&1)==0&&(a2&1)==0){
  929.           b=2;ld=ldt[SHORT];st=sdt[SHORT];
  930.         }
  931.       }
  932.       if(p->q1.flags&DREFOBJ){
  933.         p->q1.flags&=~DREFOBJ;
  934.         load_reg(f,t1,&p->q1,POINTER,t1);
  935.         p->q1.flags|=DREFOBJ;
  936.       }else{
  937.         load_address(f,t1,&p->q1,POINTER);
  938.       }
  939.       if(p->z.flags&DREFOBJ){
  940.         p->z.flags&=~DREFOBJ;
  941.         load_reg(f,t2,&p->z,POINTER,t2);
  942.         p->z.flags|=DREFOBJ;
  943.       }else{
  944.         if(c==PUSH){
  945.           if(!(p->q1.flags&VAR)) ierror(0);
  946.           if(zl2l(falign(p->q1.v->vtyp))==8) pushed=(pushed+7)/8*8;
  947.           fprintf(f,"\taddi\t%s,%s,%ld\n",mregnames[t2],mregnames[sp],pushed+8-b);
  948.           pushed+=size;
  949.         }else{
  950.           load_address(f,t2,&p->z,POINTER);
  951.         }
  952.       }
  953.       fprintf(f,"\taddi\t%s,%s,-%d\n",mregnames[t1],mregnames[t1],b);
  954.       if(c==ASSIGN) fprintf(f,"\taddi\t%s,%s,-%d\n",mregnames[t2],mregnames[t2],b);
  955.       l=size/(8*b);
  956.       if(l>1){
  957.         if((l>>16)&65535) fprintf(f,"\tlis\t%s,%lu\n",mregnames[t3],(l>>16)&65535);
  958.         fprintf(f,"\tli\t%s,%lu\n",mregnames[t3],l&65535);
  959.         fprintf(f,"\tmtctr\t%s\n",mregnames[t3]);
  960.         fprintf(f,"%s%d:\n",labprefix,++label);
  961.       }
  962.       if(l>0){
  963.         for(i=b;i<=7*b;i+=b){
  964.           fprintf(f,"\tl%s\t%s,%d(%s)\n",ld,mregnames[t3],i,mregnames[t1]);
  965.           fprintf(f,"\tst%s\t%s,%d(%s)\n",st,mregnames[t3],i,mregnames[t2]);
  966.         }
  967.         fprintf(f,"\tl%su\t%s,%d(%s)\n",ld,mregnames[t3],i,mregnames[t1]);
  968.         fprintf(f,"\tst%su\t%s,%d(%s)\n",st,mregnames[t3],i,mregnames[t2]);
  969.       }
  970.       if(l>1){
  971.         fprintf(f,"\tbdnz\t%s%d\n",labprefix,label);
  972.       }
  973.       size=size%(8*b);
  974.       for(i=0;i<size/b;i++){
  975.         fprintf(f,"\tl%su\t%s,%d(%s)\n",ld,mregnames[t3],b,mregnames[t1]);
  976.         fprintf(f,"\tst%su\t%s,%d(%s)\n",st,mregnames[t3],b,mregnames[t2]);
  977.       }
  978.       size=size%b;i=b;
  979.       if(size&2){
  980.         fprintf(f,"\tl%su\t%s,%d(%s)\n",ldt[SHORT],mregnames[t3],b,mregnames[t1]);
  981.         fprintf(f,"\tst%su\t%s,%d(%s)\n",sdt[SHORT],mregnames[t3],b,mregnames[t2]);
  982.         i=2;
  983.       }
  984.       if(size&1){
  985.         fprintf(f,"\tl%su\t%s,%d(%s)\n",ldt[CHAR],mregnames[t3],i,mregnames[t1]);
  986.         fprintf(f,"\tst%su\t%s,%d(%s)\n",sdt[CHAR],mregnames[t3],i,mregnames[t2]);
  987.       }
  988.       p->z.flags=0;
  989.       continue;
  990.     }
  991.     if(c==TEST&&((t&NQ)==FLOAT||(t&NQ)==DOUBLE)){
  992.       p->code=c=COMPARE;
  993.       p->q2.flags=KONST;
  994.       p->q2.val.vdouble=d2zd(0.0);
  995.       if((t&NQ)==FLOAT) p->q2.val.vfloat=zd2zf(p->q2.val.vdouble);
  996.     }
  997.     p=do_refs(f,p);
  998.     c=p->code;
  999.     if(c==SUBPFP) c=SUB;
  1000.     if(c==ADDI2P) c=ADD;
  1001.     if(c==SUBIFP) c=SUB;
  1002.     if(c>=CONVCHAR&&c<=CONVULONG){
  1003.       int to;
  1004.       static struct obj o;char *ip;
  1005.       if(c==CONVCHAR) to=CHAR;
  1006.       if(c==CONVUCHAR) to=UNSIGNED|CHAR;
  1007.       if(c==CONVSHORT) to=SHORT;
  1008.       if(c==CONVUSHORT) to=UNSIGNED|SHORT;
  1009.       if(c==CONVINT) to=LONG;
  1010.       if(c==CONVUINT) to=UNSIGNED|LONG;
  1011.       if(c==CONVLONG) to=LONG;
  1012.       if(c==CONVULONG) to=UNSIGNED|LONG;
  1013.       if(c==CONVFLOAT) to=FLOAT;
  1014.       if(c==CONVDOUBLE) to=DOUBLE;
  1015.       if(c==CONVPOINTER) to=UNSIGNED|LONG;
  1016.       if(to==FLOAT||to==DOUBLE){
  1017.         if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
  1018.           zreg=q1reg;
  1019.           continue;
  1020.         }
  1021.         if((t&NU)==(UNSIGNED|INT)||(t&NU)==(UNSIGNED|LONG)){
  1022.           o.flags=KONST;
  1023.           ip=(char *)&o.val.vdouble;
  1024.           ip[0]=0x41;
  1025.           ip[1]=0xe0;
  1026.           ip[2]=0x00;
  1027.           ip[3]=0x00;
  1028.           ip[4]=0x00;
  1029.           ip[5]=0x00;
  1030.           ip[6]=0x00;
  1031.           ip[7]=0x00;
  1032.           load_reg(f,f2,&o,DOUBLE,t2);
  1033.           fprintf(f,"\tfcmpu\t%s,%s,%s\n",mregnames[65],mregnames[q1reg],mregnames[f2]);
  1034.           fprintf(f,"\tcror\t3,2,1\n");
  1035.           fprintf(f,"\tbso\t%s,%s%d\n",mregnames[65],labprefix,++label);
  1036.           fprintf(f,"\tfctiwz\t%s,%s\n",mregnames[f2],mregnames[q1reg]);
  1037.           fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[DOUBLE],mregnames[f2],tmpoff-8,mregnames[sp]);
  1038.           fprintf(f,"\tl%s\t%s,%ld(%s)\n",ldt[t&NQ],mregnames[zreg],tmpoff-zl2l(sizetab[t&NQ]),mregnames[sp]);
  1039.           fprintf(f,"\tb\t%s%d\n",labprefix,++label);
  1040.           fprintf(f,"%s%d:\n",labprefix,label-1);
  1041.           fprintf(f,"\tfsub\t%s,%s,%s\n",mregnames[f2],mregnames[q1reg],mregnames[f2]);
  1042.           fprintf(f,"\tfctiwz\t%s,%s\n",mregnames[f2],mregnames[f2]);
  1043.           fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[DOUBLE],mregnames[f2],tmpoff-8,mregnames[sp]);
  1044.           fprintf(f,"\tl%s\t%s,%ld(%s)\n",ldt[INT],mregnames[zreg],tmpoff-zl2l(sizetab[t&NQ]),mregnames[sp]);
  1045.           fprintf(f,"\txoris\t%s,%s,32768\n",mregnames[zreg],mregnames[zreg]);
  1046.           fprintf(f,"%s%d:\n",labprefix,label);
  1047.         }else{
  1048.           fprintf(f,"\tfctiwz\t%s,%s\n",mregnames[f3],mregnames[q1reg]);
  1049.           fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[DOUBLE],mregnames[f3],tmpoff-8,mregnames[sp]);
  1050.           fprintf(f,"\tl%s\t%s,%ld(%s)\n",ldt[t&NQ],mregnames[zreg],tmpoff-zl2l(sizetab[t&NQ]),mregnames[sp]);
  1051.         }
  1052.         if(t==CHAR) fprintf(f,"\textsb\t%s,%s\n",mregnames[zreg],mregnames[zreg]);
  1053.         continue;
  1054.       }
  1055.       if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
  1056.         o.flags=KONST;
  1057.         ip=(char *)&o.val.vdouble;
  1058.         ip[0]=0x43;
  1059.         ip[1]=0x30;
  1060.         ip[2]=0x00;
  1061.         ip[3]=0x00;
  1062.         ip[4]=0x80;
  1063.         ip[5]=0x00;
  1064.         ip[6]=0x00;
  1065.         ip[7]=0x00;
  1066.         if((to&NU)==(UNSIGNED|INT)||(to&NU)==(UNSIGNED|LONG)){
  1067.           ip[4]=0x00;
  1068.           load_reg(f,f2,&o,DOUBLE,t2);
  1069.           fprintf(f,"\tlis\t%s,17200\n",mregnames[t2]);
  1070.           fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[INT],mregnames[q1reg],tmpoff-4,mregnames[sp]);
  1071.           fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[INT],mregnames[t2],tmpoff-8,mregnames[sp]);
  1072.           fprintf(f,"\tl%s\t%s,%ld(%s)\n",ldt[DOUBLE],mregnames[zreg],tmpoff-8,mregnames[sp]);
  1073.           fprintf(f,"\tfsub\t%s,%s,%s\n",mregnames[zreg],mregnames[zreg],mregnames[f2]);
  1074.         }else{
  1075.           fprintf(f,"\tlis\t%s,17200\n",mregnames[t2]);
  1076.           fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[INT],mregnames[t2],tmpoff-8,mregnames[sp]);
  1077.           fprintf(f,"\txoris\t%s,%s,32768\n",mregnames[t2],mregnames[q1reg]);
  1078.           fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[INT],mregnames[t2],tmpoff-4,mregnames[sp]);
  1079.           fprintf(f,"\tl%s\t%s,%ld(%s)\n",ldt[DOUBLE],mregnames[zreg],tmpoff-8,mregnames[sp]);
  1080.           load_reg(f,f2,&o,DOUBLE,t2);
  1081.           fprintf(f,"\tfsub\t%s,%s,%s\n",mregnames[zreg],mregnames[zreg],mregnames[f2]);
  1082.         }
  1083.         continue;
  1084.       }
  1085.       if((t&NQ)>=(to&NQ)){
  1086.         zreg=q1reg;
  1087.         continue;
  1088.       }else{
  1089.         if((t&NU)==CHAR) fprintf(f,"\textsb\t%s,%s\n",mregnames[zreg],mregnames[q1reg]);
  1090.         if((t&NU)==SHORT) fprintf(f,"\textsh\t%s,%s\n",mregnames[zreg],mregnames[q1reg]);
  1091.         if((t&NU)==(UNSIGNED|CHAR)) fprintf(f,"\tandi.\t%s,%s,255\n",mregnames[zreg],mregnames[q1reg]);
  1092.         if((t&NU)==(UNSIGNED|SHORT)) fprintf(f,"\tandi.\t%s,%s,65535\n",mregnames[zreg],mregnames[q1reg]);
  1093.         continue;
  1094.       }
  1095.     }
  1096.     if(c==KOMPLEMENT){
  1097.       fprintf(f,"\tnor\t%s,%s,%s\n",mregnames[zreg],mregnames[q1reg],mregnames[q1reg]);
  1098.       continue;
  1099.     }
  1100.     if(c==SETRETURN){
  1101.       if(p->z.reg){
  1102.         if(zreg==0) load_reg(f,p->z.reg,&p->q1,t,t3);
  1103.       }else
  1104.         ierror(0);
  1105.       continue;
  1106.     }
  1107.     if(c==GETRETURN){
  1108.       if(p->q1.reg)
  1109.         zreg=p->q1.reg;
  1110.       else
  1111.         p->z.flags=0;
  1112.       continue;
  1113.     }
  1114.     if(c==CALL){
  1115.       int reg;
  1116.       if((p->q1.flags&VAR)&&p->q1.v->fi&&p->q1.v->fi->inline_asm){
  1117.         fprintf(f,"%s\n",p->q1.v->fi->inline_asm);
  1118.       }else{
  1119.         if(p->q1.flags&VAR){
  1120.           if(!strcmp("__va_start",p->q1.v->identifier)){
  1121.             fprintf(f,"\taddi\t%s,%s,%ld\n",mregnames[r3],mregnames[sp],framesize+8);
  1122.             continue;
  1123.           }
  1124.           if(!strcmp("__va_regbase",p->q1.v->identifier)){
  1125.             fprintf(f,"\taddi\t%s,%s,%ld\n",mregnames[r3],mregnames[sp],regbase);
  1126.             continue;
  1127.           }
  1128.           if(!strcmp("__va_fixedgpr",p->q1.v->identifier)){
  1129.             fprintf(f,"\tli\t%s,%d\n",mregnames[r3],fixedgpr);
  1130.             continue;
  1131.           }
  1132.           if(!strcmp("__va_fixedfpr",p->q1.v->identifier)){
  1133.             fprintf(f,"\tli\t%s,%d\n",mregnames[r3],fixedfpr);
  1134.             continue;
  1135.           }
  1136.         }
  1137.         if(g_flags[10]&USEDFLAG) fprintf(f,"\tcreqv\t6,6,6\n");
  1138.         if(q1reg){
  1139.           fprintf(f,"\tmtlr\t%s\n",mregnames[q1reg]);
  1140.           fprintf(f,"\tblrl\n");
  1141.         }else{
  1142.           fprintf(f,"\tbl\t");probj2(f,&p->q1,t);
  1143.           fprintf(f,"\n");
  1144.         }
  1145.       }
  1146.       pushed-=zl2l(p->q2.val.vlong);
  1147.       continue;
  1148.     }
  1149.     if(c==ASSIGN||c==PUSH){
  1150.       if(t==0) ierror(0);
  1151.       if(q1reg){
  1152.         if(c==PUSH){
  1153.           if((t&NQ)==DOUBLE) pushed=(pushed+7)/8*8;
  1154.           fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[t&NQ],mregnames[q1reg],pushed+8,mregnames[sp]);
  1155.           pushed+=zl2l(p->q2.val.vlong);
  1156.           continue;
  1157.         }
  1158.         if(c==ASSIGN) zreg=q1reg;
  1159.         continue;
  1160.       }
  1161.     }
  1162.     if(c==ADDRESS){
  1163.       load_address(f,zreg,&p->q1,POINTER);
  1164.       continue;
  1165.     }
  1166.     if((t&NQ)==FLOAT||(t&NQ)==DOUBLE) fpp="f"; else fpp="";
  1167.     if(c==MINUS){
  1168.       fprintf(f,"\t%sneg\t%s,%s\n",fpp,mregnames[zreg],mregnames[q1reg]);
  1169.       continue;
  1170.     }
  1171.     if(c==TEST){
  1172.       if(!(p->z.flags®))
  1173.         p->z.reg=65;
  1174.       if((t&NQ)==FLOAT||(t&NQ)==DOUBLE)
  1175.         ierror(0);
  1176.       else
  1177.         fprintf(f,"\tcmp%swi\t%s,%s,0\n",(t&UNSIGNED)?"l":"",mregnames[p->z.reg],mregnames[q1reg]);
  1178.       continue;
  1179.     }
  1180.     if(c==COMPARE){
  1181.       if(!(p->z.flags®))
  1182.         p->z.reg=65;
  1183.       if((t&NQ)==FLOAT||(t&NQ)==DOUBLE)
  1184.         fprintf(f,"\tfcmpu\t%s,%s,",mregnames[p->z.reg],mregnames[q1reg]);
  1185.       else
  1186.         fprintf(f,"\tcmp%sw%s\t%s,%s,",(t&UNSIGNED)?"l":"",isimm[q2reg==0],mregnames[p->z.reg],mregnames[q1reg]);
  1187.       probj2(f,&p->q2,t);fprintf(f,"\n");
  1188.       continue;
  1189.     }
  1190.     if(c>=OR&&c<=AND){
  1191.       fprintf(f,"\t%s%s%s\t%s,%s,",logicals[c-OR],isimm[q2reg==0],(q2reg==0&&c==AND)?".":"",mregnames[zreg],mregnames[q1reg]);
  1192.       probj2(f,&p->q2,t|UNSIGNED);fprintf(f,"\n");
  1193.       continue;
  1194.     }
  1195.     if(c==SUB&&(p->q1.flags&KONST)){
  1196.       fprintf(f,"\tsubfic\t%s,%s,",mregnames[zreg],mregnames[q2reg]);
  1197.       probj2(f,&p->q1,t&NQ);fprintf(f,"\n");
  1198.       continue;
  1199.     }
  1200.     if(c>=LSHIFT&&c<=MOD){
  1201.       if(c==MOD){
  1202.         i=0;
  1203.         if(zreg==q1reg||zreg==q2reg){
  1204.           if(t1!=q1reg&&t1!=q2reg) i=t1;
  1205.           if(t2!=q1reg&&t2!=q2reg) i=t2;
  1206.         }else i=zreg;
  1207.         if(i==0||i==q1reg||i==q2reg) ierror(0);
  1208.         fprintf(f,"\tdivw%s\t%s,%s,%s\n",(t&UNSIGNED)?"u":"",mregnames[i],mregnames[q1reg],mregnames[q2reg]);
  1209.         fprintf(f,"\tmullw\t%s,%s,%s\n",mregnames[i],mregnames[i],mregnames[q2reg]);
  1210.         fprintf(f,"\tsubf\t%s,%s,%s\n",mregnames[zreg],mregnames[i],mregnames[q1reg]);
  1211.         continue;
  1212.       }
  1213.       if(c==DIV&&(t&UNSIGNED))
  1214.         fprintf(f,"\tdivwu%s\t%s,%s,",isimm[q2reg==0],mregnames[zreg],mregnames[q1reg]);
  1215.       else if(c==MULT&&((t&NQ)==FLOAT||(t&NQ)==DOUBLE))
  1216.         fprintf(f,"\tfmul\t%s,%s,",mregnames[zreg],mregnames[q1reg]);
  1217.       else if(c==DIV&&((t&NQ)==FLOAT||(t&NQ)==DOUBLE))
  1218.         fprintf(f,"\tfdiv\t%s,%s,",mregnames[zreg],mregnames[q1reg]);
  1219.       else if(c==MULT&&q2reg==0)
  1220.         fprintf(f,"\tmulli\t%s,%s,",mregnames[zreg],mregnames[q1reg]);
  1221.       else
  1222.         fprintf(f,"\t%s%s%s\t%s,%s,",fpp,arithmetics[c-LSHIFT],isimm[q2reg==0],mregnames[zreg],mregnames[q1reg]);
  1223.       probj2(f,&p->q2,t&NQ);fprintf(f,"\n");
  1224.       continue;
  1225.     }
  1226.     ierror(0);
  1227.   }
  1228.   function_bottom(f,v,of);
  1229. }
  1230.  
  1231. int shortcut(int code,int typ)
  1232. {
  1233.   return(0);
  1234. }
  1235.  
  1236. int reg_parm(struct reg_handle *m, struct Typ *t)
  1237. {
  1238.   int f;
  1239.   if(!m) ierror(0);
  1240.   if(!t) ierror(0);
  1241.   f=t->flags&NQ;
  1242.   if(f<=LONG||f==POINTER){
  1243.     if(m->gregs>=8) return(0);
  1244.     return(11-m->gregs++);
  1245.   }
  1246.   if(f==FLOAT||f==DOUBLE){
  1247.     if(m->fregs>=8) return(0);
  1248.     return(46-m->fregs++);
  1249.   }
  1250.   return(0);
  1251. }
  1252. void cleanup_cg(FILE *f)
  1253. {
  1254.   struct fpconstlist *p;
  1255.   unsigned char *ip;
  1256.   while(p=firstfpc){
  1257.     if(f){
  1258.       if(section!=RODATA){fprintf(f,rodataname);section=RODATA;}
  1259.       if((p->typ&NQ)==DOUBLE)
  1260.         fprintf(f,"\t.align\t3\n");
  1261.       else
  1262.         fprintf(f,"\t.align\t2\n");
  1263.       fprintf(f,"%s%d:\n\t.long\t",labprefix,p->label);
  1264.       ip=(unsigned char *)&p->val.vdouble;
  1265.       fprintf(f,"0x%02x%02x%02x%02x",ip[0],ip[1],ip[2],ip[3]);
  1266.       if((p->typ&NQ)==DOUBLE){
  1267.         fprintf(f,",0x%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]);
  1268.       }
  1269.       fprintf(f,"\n");
  1270.     }
  1271.     firstfpc=p->next;
  1272.     free(p);
  1273.   }
  1274. }
  1275.  
  1276.  
  1277.